/*
 * Copyright (c) 2023 WEMIRR-PLATFORM Authors. All Rights Reserved.
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.fits.framework.feign.plugin.decoder;

import com.fits.framework.core.entity.Result;
import com.fits.framework.core.exception.CheckedException;
import feign.FeignException;
import feign.Response;
import feign.codec.Decoder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.support.SpringDecoder;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @author Levin
 */
@Slf4j
@RequiredArgsConstructor
public class FeignResponseDecoder implements Decoder {

    private final SpringDecoder decoder;

    @Override
    public Object decode(Response response, Type type) throws IOException, FeignException {
        //获取feign请求对应的方法
        Method method = response.request().requestTemplate().methodMetadata().method();
        log.debug("feign decode response - {}", response);
        // 如果Feign接口的返回值不是 Response{code:0,...} 结构类型，并且远程响应又是这个结构
        //判断Feign返回类型是否是Result类型（比如接口方法返回MyResponse类，远程接口返回的是Result<MyResponse>则会进行特殊处理）
        boolean notTheSame = method.getReturnType() != Result.class;
        //状态码不是200，且不是Result类 报错
        if (response.status() != 200 && notTheSame) {
            throw new CheckedException(response.status(), response.reason());
        }
        //状态码不是200 是Result类
        if (response.status() != 200) {
            return this.decoder.decode(response, type);
        }
        //状态码是200 不是Result类
        if (notTheSame) {
            // 构造一个这个结构类型
            Type newType = new ParameterizedType() {

                @Override
                public Type[] getActualTypeArguments() {
                    return new Type[]{type};
                }

                @Override
                public Type getRawType() {
                    return Result.class;
                }

                @Override
                public Type getOwnerType() {
                    return null;
                }
            };
            //将结果转换为Result类，获取response的data到Result的结果中
            Result<?> result = (Result<?>) this.decoder.decode(response, newType);
            // 只返回data
            return result.getData();
        }
        //标准返回
        return this.decoder.decode(response, type);
    }
}